<script setup lang="ts">
// ----------------------- 导入相关依赖 -----------------------
// Vue 核心功能
import { nextTick, onMounted, reactive, ref } from 'vue'
// Element Plus 组件和类型
import { ElMessage, FormInstance } from 'element-plus'
// 自定义组件和hooks
import SysDialog from '@/components/dialog/SysDialog.vue'
import useDialog from '@/hooks/useDialog'
import useInstance from '@/hooks/useInstance'
// API相关
import { Dept, DeptListParam } from '@/api/dept/type'
import {
  addApi,
  deleteApi,
  editApi,
  getListApi,
  getTreeListApi,
} from '@/api/dept/index.ts'
// 树形选择组件
import TreeSelect from '@/components/TreeSelect/index.vue'

// ----------------------- 组件状态定义 -----------------------
// 获取全局实例和弹框方法
const { dialog, onShow, onClose } = useDialog()
const { global } = useInstance()

// 当前选中的分类ID，用于树形筛选
const currentId = ref<number>()

// 查询表单数据，包含分页信息
const searchForm = reactive<DeptListParam>({
  name: undefined,
  parentId: undefined,
  page: 1,
  limit: 15,
})

// 表格数据和总条数和加载效果
const tableData = ref([])
const total = ref(0)
const loading = ref(false)

// 表单ref，用于表单验证
const addFormRef = ref<FormInstance>()

// 新增/编辑表单数据
const addForm = reactive<Dept>({
  id: undefined,
  name: undefined,
  sort: undefined,
  status: undefined,
  parentId: undefined,
})

// ----------------------- 表单验证规则 -----------------------
const rules = {
  name: [{ required: true, message: '请输入部门名称' }],
  sort: [{ required: true, message: '请输入排序' }],
  parentId: [{ required: true, message: '请选择上级部门'}],
  status: [{ required: true, message: '请选择状态'}],
}

// ----------------------- 树形数据处理 -----------------------
// 上级分类选择器的数据
const parentOptions = ref<any[]>([])

/**
 * 获取上级分类列表数据
 * 用于新增/编辑表单中的上级分类选择
 */
const getParentCategories = async () => {
  try {
    const res = await getTreeListApi()
    if (res?.data) {
      parentOptions.value = res.data
    }
  } catch (error) {
    console.error('获取上级分类列表失败:', error)
    ElMessage.error('获取上级部门列表失败')
  }
}

// ----------------------- 左侧筛选树形数据处理 -----------------------
// 定义树节点类型
interface TreeNode {
  id: string
  name: string
  parentId: string
  children: TreeNode[]
}

// 左侧筛选树形数据
const treeData = ref<TreeNode[]>([])

/**
 * 获取左侧筛选树形数据
 */
const getTreeData = async () => {
  try {
    const res = await getTreeListApi()
    if (res?.data) {
      treeData.value = res.data
    }
  } catch (error) {
    console.error('获取树形数据失败:', error)
    ElMessage.error('获取部门数据失败')
  }
}

// ----------------------- CRUD 操作方法 -----------------------
/**
 * 获取分类列表数据
 */
const getList = async () => {
  loading.value = true
  try {
    const res = await getListApi(searchForm)
    if (res?.data) {
      tableData.value = res.data.list
      total.value = res.data.total
    }
  } catch (error) {
    console.error('获取列表数据失败:', error)
    ElMessage.error('获取列表数据失败')
  } finally {
    loading.value = false
  }
}

/**
 * 重置查询表单
 */
const resetForm = () => {
  searchForm.name = undefined
  searchForm.parentId = currentId.value || undefined
  searchForm.page = 1
  getList()
}

/**
 * 显示新增弹框
 */
const show = () => {
  dialog.title = '新增部门'
  dialog.width = 700
  nextTick(() => {
    Object.assign(addForm, {
      id: undefined,
      name: undefined,
      sort: undefined,
      parentId: undefined,
    })
    addFormRef.value?.resetFields()
    addFormRef.value?.clearValidate()
  })
  onShow()
}

/**
 * 显示编辑弹框
 */
const edit = (row: Dept) => {
  dialog.title = '编辑部门'
  dialog.width = 700
  nextTick(() => {
    Object.assign(addForm, row)
  })
  onShow()
}

/**
 * 删除分类
 */
const del = async (id: number) => {
  const confirm = await global.$myConfirm('您确定删除该数据吗？')
  if (confirm) {
    try {
      const res = await deleteApi(id)
      if (res && res.code === 200) {
        ElMessage.success('删除成功')
        getList()
        getTreeData() // 刷新树形数据
      }
    } catch (error) {
      console.error('删除失败:', error)
      ElMessage.error('删除失败')
    }
  }
}

/**
 * 保存分类（新增/编辑）
 */
const save = async () => {
  if (!addFormRef.value) return
  await addFormRef.value.validate(async (valid) => {
    if (valid) {
      try {
        let res
        if (addForm.id) {
          res = await editApi(addForm)
        } else {
          res = await addApi(addForm)
        }
        if (res && res.code === 200) {
          ElMessage.success(addForm.id ? '修改成功' : '新增成功')
          onClose()
          getList()
          getTreeData() // 刷新树形数据
          addFormRef.value?.resetFields()
        }
      } catch (error) {
        console.error('保存失败:', error)
        ElMessage.error('保存失败')
      }
    }
  })
}

// ----------------------- 分页相关方法 -----------------------
/**
 * 页码改变处理
 */
const handleCurrentChange = (val: number) => {
  searchForm.page = val
  getList()
}

/**
 * 每页条数改变处理
 */
const handleSizeChange = (val: number) => {
  searchForm.limit = val
  getList()
}

// ----------------------- 其他方法 -----------------------
/**
 * 关闭弹框
 */
const closeDialog = () => {
  addFormRef.value?.resetFields()
  addFormRef.value?.clearValidate()
  onClose()
}

/**
 * 树节点点击事件处理
 */
const handleTreeNodeClick = async (data: any) => {
  // 处理虚拟顶级节点点击
  if (data.id === '-1') {
    currentId.value = undefined
    searchForm.parentId = undefined
  } else {
    currentId.value = data.id
    searchForm.parentId = data.id
  }

  // 重置分页和搜索条件
  searchForm.page = 1
  searchForm.limit = 10
  searchForm.name = undefined
  await getList()
}

// 表格高度自适应
const tableHeight = ref(0)

// ----------------------- 生命周期钩子 -----------------------
onMounted(() => {
  // 设置表格高度
  nextTick(() => {
    tableHeight.value = window.innerHeight - 270
  })
  // 初始化数据
  getTreeData()
  getList()
  getParentCategories()
})
</script>

<template>
  <el-main>
    <el-row :gutter="20">
      <!-- 左侧树形菜单 -->
      <el-col :span="4">
        <TreeSelect :data="treeData"
                    :props="{
              children: 'children',
              label: 'name'
            }"
                    placeholder="请输入部门名称"
                    @node-click="handleTreeNodeClick" />
      </el-col>

      <!-- 右侧内容区 -->
      <el-col :span="20">
        <el-card style="height: 75px;">
          <!-- 搜索表单 -->
          <el-form :inline="true"
                   :model="searchForm">
            <el-form-item label="部门名称">
              <el-input v-model="searchForm.name"
                        placeholder="请输入部门名称" />
            </el-form-item>
            <el-form-item>
              <el-button type="primary"
                         @click="getList"
                         icon="search">查询</el-button>
              <el-button @click="resetForm"
                         icon="Refresh">重置</el-button>
              <el-button type="success"
                         @click="show"
                         icon="Plus">新增</el-button>
            </el-form-item>
          </el-form>
        </el-card>

        <!-- 表格 -->
        <el-table v-loading="loading"
                  :data="tableData"
                  border
                  style="width: 100%;margin-top: 15px"
                  :height="tableHeight"
                  stripe>
          <el-table-column type="index"
                           label="序号"
                           width="70" />
          <el-table-column prop="name"
                           label="部门名称"
                           width="190" />
          <el-table-column prop="sort"
                           label="排序" />
          <el-table-column prop="status"
                           label="状态">
            <template #default="scope">
              <el-tag type="primary"
                      v-if="scope.row.status == 0">正常</el-tag>
              <el-tag type="danger"
                      v-else>禁用</el-tag>
            </template>
          </el-table-column>
          <el-table-column prop="createTime"
                           label="创建时间" />
          <el-table-column prop="updateTime"
                           label="更新时间" />
          <el-table-column label="操作"
                           width="180"
                           fixed="right">
            <template #default="scope">
              <el-button type="primary"
                         size="small"
                         icon="edit"
                         link
                         @click="edit(scope.row)">编辑</el-button>
              <el-button type="danger"
                         size="small"
                         icon="Delete"
                         link
                         @click="del(scope.row.id)">删除</el-button>
            </template>
          </el-table-column>
        </el-table>

        <!-- 分页 -->
        <el-pagination
            v-model:current-page="searchForm.page"
            v-model:page-size="searchForm.limit"
            :page-sizes="[10, 20, 30, 40, 50]"
            :total="total"
            background
            @size-change="handleSizeChange"
            @current-change="handleCurrentChange"
            layout="total, sizes, prev, pager, next, jumper"
        />
      </el-col>
    </el-row>

    <!-- 新增/编辑弹框 -->
    <sys-dialog :title="dialog.title"
                :width="dialog.width"
                :visible="dialog.visible"
                @onClose="closeDialog"
                @onConfirm="save">
      <template #content>
        <el-form ref="addFormRef"
                 :model="addForm"
                 :rules="rules"
                 label-width="100px"
                 class="dept-form">
          <el-row :gutter="20">
            <!-- 部门名称 -->
            <el-col :span="12">
              <el-form-item label="部门名称"
                            prop="name">
                <el-input v-model="addForm.name"
                          placeholder="请输入部门名称"
                          clearable />
              </el-form-item>
            </el-col>

            <!-- 上级部门 -->
            <el-col :span="12">
              <el-form-item label="上级部门"
                            prop="parentId"
                            v-if="addForm.parentId!=0">
                <el-tree-select v-model="addForm.parentId"
                                :data="parentOptions"
                                :render-after-expand="false"
                                placeholder="请选择上级部门"
                                show-checkbox
                                check-strictly
                                clearable
                                class="flex-1" />
              </el-form-item>
            </el-col>
          </el-row>

          <el-row :gutter="20">
            <!-- 排序 -->
            <el-col :span="12">
              <el-form-item label="显示排序"
                            prop="sort">
                <el-input-number v-model="addForm.sort"
                                 :min="0"
                                 :max="999"
                                 controls-position="right"
                                 placeholder="请输入显示排序"
                                 class="flex-1" />
              </el-form-item>
            </el-col>

            <!-- 状态 -->
            <el-col :span="12">
              <el-form-item label="部门状态"
                            prop="status">
                <el-radio-group v-model="addForm.status">
                  <el-radio :value=0>正常</el-radio>
                  <el-radio :value=1>停用</el-radio>
                </el-radio-group>
              </el-form-item>
            </el-col>
          </el-row>
        </el-form>
      </template>
    </sys-dialog>
  </el-main>
</template>

<style lang="scss" scoped>
.dept-form {
  padding: 20px;

  :deep(.el-form-item) {
    margin-bottom: 20px;

    .el-form-item__label {
      font-weight: 500;
      color: #606266;
    }

    .el-form-item__content {
      .el-input,
      .el-tree-select,
      .el-input-number {
        width: 100%;

        .el-input__wrapper {
          box-shadow: 0 0 0 1px #dcdfe6 inset;

          &:hover {
            box-shadow: 0 0 0 1px #409eff inset;
          }

          &.is-focus {
            box-shadow: 0 0 0 1px #409eff inset;
          }
        }
      }

      .el-radio-group {
        .el-radio {
          margin-right: 20px;

          &:last-child {
            margin-right: 0;
          }

          .el-radio__label {
            font-weight: normal;
          }
        }
      }
    }
  }

  // 行间距
  .el-row {
    margin-bottom: 10px;

    &:last-child {
      margin-bottom: 0;
    }
  }

  // 响应式处理
  @media screen and (max-width: 768px) {
    .el-col {
      width: 100%;
    }

    :deep(.el-form-item) {
      margin-bottom: 15px;
    }
  }
}

// 工具类
.flex-1 {
  flex: 1;
  width: 100%;
}
</style>
